# Copyright (c) 2005,2006,2007 Dynamic Solutions Inc. (support@dynamic-solutions.com)
#
# This file is part of DataZoomer.
#
# DataZoomer is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# DataZoomer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""DataZoomer Response class

All DataZoomer applications have to do basically one thing.  They have to
return a Response object.  This module contains the basic Response class
definition and some common subclasses such as HTMLResponse, PNGResponse, etc..
"""


from zoom import zoomer
from os.path import join, abspath
from mimetypes import guess_type


class Response:
    def __init__(self):
        self.headers = {}
        self.content = ''
    def render_headers(self):
        t = ''
        for header, value in self.headers.items():
            t += "%s: %s\n" % (header, value)
        t += '\n'
        return t
    def render(self):
        return self.render_headers() + self.content

class HTMLResponse(Response):
    def __init__(self,content=''):
        Response.__init__(self)
        self.content       = content
        self.headers['Content-type']  = 'text/html'
        self.headers['Cache-Control'] = 'no-cache'
    def render(self):
        doc_list = []

        if zoomer.show_debug_info() and zoomer.printed_output:
            po = zoomer.printed_output
        else:
            po = ''

        if zoomer.show_debug_info():
            debug_output = zoomer.debug.content()
        else:
            debug_output = ''

        content = self.content.replace('<#DEBUG>',debug_output).replace('<#PRINTED_OUTPUT>',po)

        doc_list.append(content)

        doc = ''.join(doc_list)

        self.headers['Content-length'] = ('%s' % len(doc))
        return self.render_headers() + doc

class XMLResponse(Response):
    def __init__(self,content=''):
        Response.__init__(self)
        self.content       = content
        self.headers['Content-type']  = 'text/xml'
        self.headers['Cache-Control'] = 'no-cache'

    def render(self):
        doc = '<?xml version="1.0"?>%s' % self.content
        self.headers['Content-length'] = ('%s' % len(doc))
        return self.render_headers() + doc

class ImageResponse(Response):
    def __init__(self,imagename,themename):
        Response.__init__(self)

        theme_path = '%s/themes/%s/images' % (zoomer.site_path,themename)
        f = abspath(join(theme_path,imagename))

        self.subtype = guess_type(f)
        self.content = open(f,'rb').read()

        self.headers['Content-type'] = self.subtype[0] and self.subtype[0] or 'image/jpeg'
        if self.subtype[1]: self.headers['Content-Encoding'] = self.subtype[1]
        self.headers['Cache-Control'] = 'no-cache'
    def render(self):
        doc = self.content
        self.headers['Content-length'] = ('%s' % len(doc))
        return '%s%s' % (self.render_headers(),doc)

class PDFResponse(Response):
    def __init__(self,content=''):
        Response.__init__(self)
        self.content       = content
        self.headers['Content-type']  = 'application/pdf'
        self.headers['Cache-Control'] = 'no-cache'
    def render(self):
        doc = self.content
        self.headers['Content-length'] = ('%s' % len(doc))
        return self.render_headers() + doc

class ExceptionResponse(HTMLResponse):
    def __init__(self,content=None):
        Response.__init__(self)
        self.exception = content
        self.headers['Content-type']  = 'text/html'
        self.headers['Cache-Control'] = 'no-cache'

    def render(self):
        doc_list = []

        if zoomer.show_debug_info() and zoomer.printed_output:
            doc_list.append('<pre>%s</pre><br>' % zoomer.printed_output)


        exception = self.exception.replace('\n','<br />').replace('  ','&nbsp;&nbsp;').replace(zoomer.root_path,'.')
        t = open(join(zoomer.theme_path,'default/templates/errormsg.html'),'r')
        errpage = ''.join(t.readlines())
        t.close()
        exception = errpage.replace('<#MSG>','<pre>%s</pre>' % (exception))
        doc_list.append(exception)

        if zoomer.show_debug_info():
            doc_list.append('%s' % zoomer.debug.content())

        doc = ''.join(doc_list)
        self.headers['Content-length'] = ('%s' % len(doc))

        return self.render_headers() + doc

class FileResponse(Response):
    def __init__(self,filename):
        Response.__init__(self)
        self.content = file(filename,'rb').read()
        import os
        (path,fileonly) = os.path.split(filename)
        self.headers['Content-type']  = 'application/octet-stream'
        self.headers['Content-Disposition'] = 'attachment; filename="%s"' % fileonly
        self.headers['Cache-Control'] = 'no-cache'
    def render(self):
        doc = self.content
        self.headers['Content-length'] = ('%s' % len(doc))
        return self.render_headers() + doc

# ---- ToDo -------------
# class DownloadFileResponse(Response)
# class JPGResponse(Response)
# class PNGResponse(Response)
# class ExcelResponse(Response)
# class PdfResponse(Response)
# class AudioStreamResponse(Response)
# class MediaPlayerResponse(Response)
# class SkypeResponse(Response)

class RedirectResponse(Response):
    def __init__(self,url):
        Response.__init__(self)
        self.headers['Location']  = url
        self.content = ''

class LoginResponse(RedirectResponse):
    def __init__(self):
        RedirectResponse.__init__(self,zoomer.authentication_url)


if __name__ == '__main__':
    import unittest

    class AppTest(unittest.TestCase):

        #----------------------
        def test_Response(self):
            response = Response()
            self.assertEquals(response.render(),'\n')
            response.content = 'Hi'
            self.assertEquals(response.render(),'\nHi')
            response.headers['one'] = 'two'
            self.assertEquals(response.render(),'one: two\n\nHi')

        def test_HTMLResponse(self):
            response = HTMLResponse('Hello World!')
            zoomer.printed_output = 'pout'
            zoomer.debugging = 0
            target = 'Content-length: 12\nContent-type: text/html\nCache-Control: no-cache\n\n<pre>pout</pre><br>Hello World!'
            self.assertEquals(response.render(),target)

        def test_RedirectResponse(self):
            response = RedirectResponse('http://datazoomer.org')
            answer = 'Location: http://datazoomer.org\n\n'
            self.assertEquals(response.render(),answer)

    unittest.main()
